home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / qksort.com / QKSORT.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1990-03-01  |  5.4 KB  |  172 lines

  1. {$A-,B-,D+,E-,F-,I+,L+,N-,O-,R-,S+,V-}
  2.  
  3. unit qksort;
  4.  
  5. {
  6. ------------------------------------------------------------------------
  7. QKSORT.PAS  -  Quicksort and binary search routines
  8.  
  9. Author:        Robert J. Showalter
  10. CompuServe ID: 72220,466
  11.  
  12. Revised 05/09/89 to correct problem with sort algorithm.
  13.  
  14. Compile with Turbo Pascal v5.0 or higher.
  15.  
  16. Description of interface:
  17.  
  18.    procedure qsort(var b; nr,r : integer; f : fcmp_type);
  19.  
  20.       b             = memory array being sorted.  may be of any type.
  21.       nr            = number of records (elements) in array (<=maxint)
  22.       r             = record length, in bytes
  23.       f             = user-written comparison function.  this function
  24.                       is passed pointers to two records, p1 and p2.
  25.                       it should compare the two records and return an
  26.                       integer based on their rank in the desired
  27.                       sort order:
  28.                          <0 : record p1 should come BEFORE record p2
  29.                           0 : the two records are equal in rank
  30.                          >0 : record p1 should come AFTER record p2
  31.  
  32.    function bsearch(var key,var b; nr,r : integer; f : fcmp_type) : integer;
  33.  
  34.       key           = key value being searched for.  may be of any type.
  35.       b             = memory array being sorted.  may be of any type.
  36.       nr            = number of records (elements) in array (<=maxint)
  37.       r             = record length, in bytes
  38.       f             = user-written comparison function.  this function
  39.                       is passed a record pointers, p1, and a pointer to
  40.                       the key, p2.  it should compare the two record
  41.                       with the key value and return an integer based
  42.                       on the comparison:
  43.                       sort order:
  44.                          <0 : record p1 comes BEFORE the key value, p2.
  45.                           0 : record p1 matches the key value, p2.
  46.                          >0 : record p1 should come AFTER the key value, p2.
  47.  
  48.       If the key value was found, bsearch returns the RECORD NUMBER of the
  49.       matching record (in the range 0..nr-1).  If the key value was not
  50.       found, bsearch returns -1.
  51. ------------------------------------------------------------------------
  52. }
  53.  
  54. interface
  55.  
  56. type
  57.    fcmp_type        = function(var p1,p2) : integer;
  58.  
  59. procedure qsort(var b; nr,r : integer; f : fcmp_type);
  60. function bsearch(var key,b; nr,r : integer; f : fcmp_type) : integer;
  61.  
  62.  
  63. implementation
  64.  
  65. type
  66.    buf_type         = array[0..0] of byte;
  67.  
  68. var
  69.    buffer           : ^buf_type;
  70.    fcmp             : fcmp_type;        { pointer to compare function }
  71.    reclen           : word;             { record length }
  72.  
  73. {----------------------------------------------------------------------}
  74.  
  75. procedure swapbytes(var a,b; len : word);
  76.  
  77. begin
  78.    inline(
  79.       $1E/          { push ds           ; save DS reg }
  80.       $8B/$8E/len/  { mov cx,[bp+4]     ; CX = len }
  81.       $C5/$B6/a/    { lds si,[bp+10]    ; DS:SI = var a }
  82.       $C4/$BE/b/    { les di,[bp+6]     ; ES:DI = var b }
  83.       $FC/          { cld               ; set forward direction }
  84.       $8A/$04/      { mov al,[SI]       ; get a }
  85.       $8A/$25/      { mov ah,[DI]       ; get b }
  86.       $88/$24/      { mov [SI],ah       ; store a }
  87.       $AA/          { stosb             ; store b }
  88.       $46/          { inc si            ; increment }
  89.       $E2/$F6/      { loop ...          ; continue }
  90.       $1F           { pop ds            ; restore DS reg }
  91.    );
  92. end;
  93.  
  94. {----------------------------------------------------------------------}
  95.  
  96. { QuickSort algorithm }
  97.  
  98. procedure sort(l,r: integer);
  99.  
  100. var
  101.    i,j,x             : word;
  102.    pivot             : ^buf_type;       { "pivot" value }
  103.  
  104. begin
  105.    i := l;
  106.    j := r;
  107.    x := (l + r) div 2;
  108.    getmem(pivot,reclen);                { allocate pivot buffer }
  109.    move(buffer^[x*reclen],pivot^,reclen);  { get pivot value }
  110.    repeat
  111.       while fcmp(buffer^[i*reclen],pivot^) < 0 do inc(i);
  112.       while fcmp(pivot^,buffer^[j*reclen]) < 0 do dec(j);
  113.       if integer(i) <= integer(j) then begin
  114.          swapbytes(buffer^[i*reclen],buffer^[j*reclen],reclen);
  115.          inc(i);
  116.          dec(j);
  117.       end;
  118.    until integer(i) > integer(j);
  119.    freemem(pivot,reclen);               { deallocate pivot buffer }
  120.    if integer(l) < integer(j) then sort(l,j);
  121.    if integer(i) < integer(r) then sort(i,r);
  122. end;
  123.  
  124. {----------------------------------------------------------------------}
  125.  
  126. procedure qsort;
  127.  
  128. begin
  129.    buffer := @b;
  130.    reclen := r;
  131.    fcmp := f;
  132.    sort(0,pred(nr));
  133. end;
  134.  
  135. {----------------------------------------------------------------------}
  136.  
  137. function bsearch;
  138.  
  139. var
  140.    l,u,i,j          : integer;
  141.    done             : boolean;
  142.  
  143. begin
  144.    buffer := @b;
  145.    l := 0;
  146.    u := nr;
  147.    done := false;
  148.    while not done do begin
  149.       i := (l+u) div 2;                 { compute midpoint of range }
  150.       j := f(buffer^[i * r],key);
  151.       if j=0 then begin
  152.          bsearch := i;
  153.          done := true;
  154.       end else if j<0 then begin
  155.          if l=i then begin
  156.             bsearch := -1;
  157.             done := true;
  158.          end else
  159.             l := i;
  160.       end else begin
  161.          if u=i then begin
  162.             bsearch := -1;
  163.             done := true;
  164.          end else
  165.             u := i;
  166.       end;
  167.    end;
  168. end;
  169.  
  170.  
  171. end.
  172.